1 package net.sourceforge.simplegamenet.chess; 2 3 import java.io.Serializable; 4 5 public class ChessPlayField implements ChessGridSize, ChessPlayFieldState, ChessPieceType, 6 ChessPieceOwner, Serializable { 7 8 public static final int[][] DEFAULT_PIECE_TYPE_GRID = { 9 {ROOK, PAWN, NO_TYPE, NO_TYPE, NO_TYPE, NO_TYPE, PAWN, ROOK}, 10 {KNIGHT, PAWN, NO_TYPE, NO_TYPE, NO_TYPE, NO_TYPE, PAWN, KNIGHT}, 11 {BISHOP, PAWN, NO_TYPE, NO_TYPE, NO_TYPE, NO_TYPE, PAWN, BISHOP}, 12 {QUEEN, PAWN, NO_TYPE, NO_TYPE, NO_TYPE, NO_TYPE, PAWN, QUEEN}, 13 {KING, PAWN, NO_TYPE, NO_TYPE, NO_TYPE, NO_TYPE, PAWN, KING}, 14 {BISHOP, PAWN, NO_TYPE, NO_TYPE, NO_TYPE, NO_TYPE, PAWN, BISHOP}, 15 {KNIGHT, PAWN, NO_TYPE, NO_TYPE, NO_TYPE, NO_TYPE, PAWN, KNIGHT}, 16 {ROOK, PAWN, NO_TYPE, NO_TYPE, NO_TYPE, NO_TYPE, PAWN, ROOK} 17 }; 18 public static final int[][] DEFAULT_PIECE_OWNER_GRID = { 19 { 20 BLACK_OWNER, BLACK_OWNER, NO_OWNER, NO_OWNER, 21 NO_OWNER, NO_OWNER, WHITE_OWNER, WHITE_OWNER 22 }, 23 { 24 BLACK_OWNER, BLACK_OWNER, NO_OWNER, NO_OWNER, 25 NO_OWNER, NO_OWNER, WHITE_OWNER, WHITE_OWNER 26 }, 27 { 28 BLACK_OWNER, BLACK_OWNER, NO_OWNER, NO_OWNER, 29 NO_OWNER, NO_OWNER, WHITE_OWNER, WHITE_OWNER 30 }, 31 { 32 BLACK_OWNER, BLACK_OWNER, NO_OWNER, NO_OWNER, 33 NO_OWNER, NO_OWNER, WHITE_OWNER, WHITE_OWNER 34 }, 35 { 36 BLACK_OWNER, BLACK_OWNER, NO_OWNER, NO_OWNER, 37 NO_OWNER, NO_OWNER, WHITE_OWNER, WHITE_OWNER 38 }, 39 { 40 BLACK_OWNER, BLACK_OWNER, NO_OWNER, NO_OWNER, 41 NO_OWNER, NO_OWNER, WHITE_OWNER, WHITE_OWNER 42 }, 43 { 44 BLACK_OWNER, BLACK_OWNER, NO_OWNER, NO_OWNER, 45 NO_OWNER, NO_OWNER, WHITE_OWNER, WHITE_OWNER 46 }, 47 { 48 BLACK_OWNER, BLACK_OWNER, NO_OWNER, NO_OWNER, 49 NO_OWNER, NO_OWNER, WHITE_OWNER, WHITE_OWNER 50 } 51 }; 52 53 public static boolean isCheckState(ChessPiece[] checkingPieceGrid, 54 int participantsOwnerIndex) { 55 int kingX = -1; 56 int kingY = -1; 57 for (int i = 0; i < checkingPieceGrid.length; i++) { 58 if (checkingPieceGrid[i] != null && checkingPieceGrid[i] instanceof ChessKing 59 && checkingPieceGrid[i].getParticipantsOwnerIndex() 60 == participantsOwnerIndex) { 61 kingX = checkingPieceGrid[i].getX(); 62 kingY = checkingPieceGrid[i].getY(); 63 break; 64 } 65 } 66 for (int i = 0; i < GRID_HEIGHT * GRID_WIDTH; i++) { 67 if (checkingPieceGrid[i] != null 68 && checkingPieceGrid[i].getParticipantsOwnerIndex() != participantsOwnerIndex 69 && checkingPieceGrid[i].isMoveAllowed(checkingPieceGrid, kingX, kingY)) { 70 return true; 71 } 72 } 73 return false; 74 } 75 76 public static boolean isCheckAfterMoveState(ChessPiece[] checkingPieceGrid, 77 int participantsOwnerIndex) { 78 for (int i = 0; i < checkingPieceGrid.length; i++) { 79 if (checkingPieceGrid[i] != null 80 && checkingPieceGrid[i].getParticipantsOwnerIndex() 81 == participantsOwnerIndex) { 82 for (int j = 0; j < checkingPieceGrid.length; j++) { 83 if (checkingPieceGrid[i].isMoveAllowed(checkingPieceGrid, 84 j / GRID_HEIGHT, j % GRID_HEIGHT)) { 85 ChessPiece[] tempPieceGrid = new ChessPiece[checkingPieceGrid.length]; 86 for (int k = 0; k < tempPieceGrid.length; k++) { 87 if (checkingPieceGrid[k] != null) { 88 tempPieceGrid[k] = (ChessPiece) checkingPieceGrid[k].clone(); 89 } 90 } 91 tempPieceGrid[i].doMove(tempPieceGrid, 92 j / GRID_HEIGHT, j % GRID_HEIGHT); 93 if (!isCheckState(tempPieceGrid, participantsOwnerIndex)) { 94 return false; 95 } 96 } 97 } 98 } 99 } 100 return true; 101 } 102 103 private Integer[] participantsOrder; 104 105 private int state = NORMAL_STATE; 106 private boolean waitingForRemiseOfferAnswer = false; 107 108 private int participantAtTurnIndex = 0; 109 110 private ChessPiece[] pieceGrid = new ChessPiece[GRID_WIDTH * GRID_HEIGHT]; 111 112 public ChessPlayField(Integer[] participantsOrder) { 113 this.participantsOrder = participantsOrder; 114 for (int i = 0; i < GRID_WIDTH; i++) { 115 for (int j = 0; j < GRID_HEIGHT; j++) { 116 ChessPiece chessPiece = null; 117 int participantOwnerIndex = -1; 118 switch (DEFAULT_PIECE_OWNER_GRID[i][j]) { 119 case WHITE_OWNER: 120 participantOwnerIndex = 0; 121 break; 122 case BLACK_OWNER: 123 participantOwnerIndex = 1; 124 break; 125 } 126 switch (DEFAULT_PIECE_TYPE_GRID[i][j]) { 127 case KING: 128 chessPiece = new ChessKing(participantOwnerIndex, i, j); 129 break; 130 case QUEEN: 131 chessPiece = new ChessQueen(participantOwnerIndex, i, j); 132 break; 133 case BISHOP: 134 chessPiece = new ChessBishop(participantOwnerIndex, i, j); 135 break; 136 case KNIGHT: 137 chessPiece = new ChessKnight(participantOwnerIndex, i, j); 138 break; 139 case ROOK: 140 chessPiece = new ChessRook(participantOwnerIndex, i, j); 141 break; 142 case PAWN: 143 chessPiece = new ChessPawn(participantOwnerIndex, i, j); 144 break; 145 } 146 pieceGrid[i * GRID_HEIGHT + j] = chessPiece; 147 } 148 } 149 } 150 151 public Integer getParticipantAtTurnPlayerID() { 152 return participantsOrder[participantAtTurnIndex]; 153 } 154 155 public boolean isMoveAllowed(int sourceX, int sourceY, 156 int destinationX, int destinationY, int chosenPieceType) { 157 if (sourceX < 0 || sourceY < 0 || destinationX < 0 || destinationY < 0 158 || sourceX >= GRID_WIDTH || sourceY >= GRID_HEIGHT 159 || destinationX >= GRID_WIDTH || destinationY >= GRID_HEIGHT) { 160 return false; 161 } 162 if (isMoveAllowed(sourceX, sourceY, destinationX, destinationY)) { 163 if (isReplaceChoiceNeeded(sourceX, sourceY, destinationX, destinationY)) { 164 switch (chosenPieceType) { 165 case QUEEN: 166 return true; 167 case BISHOP: 168 return true; 169 case KNIGHT: 170 return true; 171 case ROOK: 172 return true; 173 default: 174 return false; 175 } 176 } else { 177 return true; 178 } 179 } else { 180 return false; 181 } 182 } 183 184 private boolean isMoveAllowed(int sourceX, int sourceY, 185 int destinationX, int destinationY) { 186 if (pieceGrid[sourceX * GRID_HEIGHT + sourceY] == null) { 187 return false; 188 } 189 if (pieceGrid[sourceX * GRID_HEIGHT + sourceY] 190 .isMoveAllowed(pieceGrid, destinationX, destinationY)) { 191 ChessPiece[] tempPieceGrid = new ChessPiece[pieceGrid.length]; 192 for (int i = 0; i < tempPieceGrid.length; i++) { 193 if (pieceGrid[i] != null) { 194 tempPieceGrid[i] = (ChessPiece) pieceGrid[i].clone(); 195 } 196 } 197 tempPieceGrid[sourceX * GRID_HEIGHT + sourceY] 198 .doMove(tempPieceGrid, destinationX, destinationY); 199 return !isCheckState(tempPieceGrid, 200 tempPieceGrid[destinationX * GRID_HEIGHT + destinationY] 201 .getParticipantsOwnerIndex()); 202 } else { 203 return false; 204 } 205 } 206 207 public int doMove(int sourceX, int sourceY, int destinationX, int destinationY, 208 int chosenPieceType) { 209 if (isReplaceChoiceNeeded(sourceX, sourceY, destinationX, destinationY)) { 210 pieceGrid[sourceX * GRID_HEIGHT + sourceY].doMove(pieceGrid, 211 destinationX, destinationY); 212 switch (chosenPieceType) { 213 case QUEEN: 214 pieceGrid[destinationX * GRID_HEIGHT + destinationY] 215 = new ChessQueen(pieceGrid[destinationX * GRID_HEIGHT + destinationY] 216 .getParticipantsOwnerIndex(), 217 destinationX, destinationY); 218 break; 219 case BISHOP: 220 pieceGrid[destinationX * GRID_HEIGHT + destinationY] 221 = new ChessBishop(pieceGrid[destinationX * GRID_HEIGHT + destinationY] 222 .getParticipantsOwnerIndex(), 223 destinationX, destinationY); 224 break; 225 case KNIGHT: 226 pieceGrid[destinationX * GRID_HEIGHT + destinationY] 227 = new ChessKnight(pieceGrid[destinationX * GRID_HEIGHT + destinationY] 228 .getParticipantsOwnerIndex(), 229 destinationX, destinationY); 230 break; 231 case ROOK: 232 pieceGrid[destinationX * GRID_HEIGHT + destinationY] 233 = new ChessRook(pieceGrid[destinationX * GRID_HEIGHT + destinationY] 234 .getParticipantsOwnerIndex(), 235 destinationX, destinationY); 236 break; 237 } 238 } else { 239 pieceGrid[sourceX * GRID_HEIGHT + sourceY].doMove(pieceGrid, 240 destinationX, destinationY); 241 } 242 participantAtTurnIndex = (participantAtTurnIndex + 1) % participantsOrder.length; 243 if (isCheckState(pieceGrid, participantAtTurnIndex)) { 244 if (isCheckAfterMoveState(pieceGrid, participantAtTurnIndex)) { 245 state = CHECKMATE; 246 participantAtTurnIndex = (participantAtTurnIndex + 1) 247 % participantsOrder.length; 248 } else { 249 state = CHECK; 250 } 251 } else { 252 if (isCheckAfterMoveState(pieceGrid, participantAtTurnIndex)) { 253 state = STALEMATE; 254 participantAtTurnIndex = -1; 255 } else { 256 state = NORMAL_STATE; 257 } 258 } 259 return state; 260 } 261 262 public void setWaitingForRemiseOfferAnswer() { 263 waitingForRemiseOfferAnswer = true; 264 } 265 266 public int setRemiseOfferAnswer(boolean remiseOfferAccepted) { 267 waitingForRemiseOfferAnswer = false; 268 if (remiseOfferAccepted) { 269 state = REMISE; 270 participantAtTurnIndex = -1; 271 } 272 return state; 273 } 274 275 public int yieldGame(Integer playerID) { 276 int participantsIndex = 0; 277 for (int i = 0; i < participantsOrder.length; i++) { 278 if (participantsOrder[i].equals(playerID)) { 279 participantsIndex = i; 280 break; 281 } 282 } 283 state = YIELDED; 284 participantAtTurnIndex = (participantsIndex + 1) % participantsOrder.length; 285 return state; 286 } 287 288 public boolean[][] getMoveSourceAllowedGrid() { 289 boolean[][] moveSourceAllowedGrid = new boolean[GRID_WIDTH][GRID_HEIGHT]; 290 for (int i = 0; i < GRID_WIDTH; i++) { 291 for (int j = 0; j < GRID_HEIGHT; j++) { 292 moveSourceAllowedGrid[i][j] = pieceGrid[i * GRID_HEIGHT + j] != null 293 && pieceGrid[i * GRID_HEIGHT + j] 294 .getParticipantsOwnerIndex() 295 == participantAtTurnIndex; 296 } 297 } 298 return moveSourceAllowedGrid; 299 } 300 301 public boolean[][] getMoveDestinationAllowedGrid(int sourceX, int sourceY) { 302 boolean[][] moveDestinationAllowedGrid = new boolean[GRID_WIDTH][GRID_HEIGHT]; 303 for (int i = 0; i < GRID_HEIGHT; i++) { 304 for (int j = 0; j < GRID_WIDTH; j++) { 305 moveDestinationAllowedGrid[i][j] = isMoveAllowed(sourceX, sourceY, i, j); 306 } 307 } 308 return moveDestinationAllowedGrid; 309 } 310 311 public boolean isReplaceChoiceNeeded(int sourceX, int sourceY, 312 int destinationX, int destinationY) { 313 return pieceGrid[sourceX * GRID_HEIGHT + sourceY] != null 314 && pieceGrid[sourceX * GRID_HEIGHT + sourceY] instanceof ChessPawn 315 && ((ChessPawn) pieceGrid[sourceX * GRID_HEIGHT + sourceY]) 316 .isReplaceChoiceNeeded(destinationX, destinationY); 317 } 318 319 public int getPieceOwnerSight(Integer clientPlayerID) { 320 if (clientPlayerID.equals(participantsOrder[0])) { 321 return WHITE_OWNER; 322 } else if (clientPlayerID.equals(participantsOrder[1])) { 323 return BLACK_OWNER; 324 } 325 return NO_OWNER; 326 } 327 328 public int getPlayFieldState() { 329 return state; 330 } 331 332 public int[][] getPieceTypeGrid() { 333 int[][] pieceTypeGrid = new int[GRID_WIDTH][GRID_HEIGHT]; 334 for (int i = 0; i < GRID_WIDTH; i++) { 335 for (int j = 0; j < GRID_HEIGHT; j++) { 336 if (pieceGrid[i * GRID_HEIGHT + j] == null) { 337 pieceTypeGrid[i][j] = NO_TYPE; 338 } else { 339 pieceTypeGrid[i][j] = pieceGrid[i * GRID_HEIGHT + j].getPieceType(); 340 } 341 } 342 } 343 return pieceTypeGrid; 344 } 345 346 public int[][] getPieceOwnerGrid() { 347 int[][] pieceOwnerGrid = new int[GRID_WIDTH][GRID_HEIGHT]; 348 for (int i = 0; i < GRID_WIDTH; i++) { 349 for (int j = 0; j < GRID_HEIGHT; j++) { 350 if (pieceGrid[i * GRID_HEIGHT + j] == null) { 351 pieceOwnerGrid[i][j] = NO_OWNER; 352 } else { 353 switch (pieceGrid[i * GRID_HEIGHT + j].getParticipantsOwnerIndex()) { 354 case 0: 355 pieceOwnerGrid[i][j] = WHITE_OWNER; 356 break; 357 case 1: 358 pieceOwnerGrid[i][j] = BLACK_OWNER; 359 break; 360 default: 361 pieceOwnerGrid[i][j] = NO_OWNER; 362 break; 363 } 364 } 365 } 366 } 367 return pieceOwnerGrid; 368 } 369 370 public int getState() { 371 return state; 372 } 373 374 public ChessPiece[] getPieceGrid() { 375 return pieceGrid; 376 } 377 378 }